{$IFDEF FPC}{$mode objfpc}{$ENDIF}
{$IFDEF VER180}
 {$DEFINE COMPILER2006}
 {$IFDEF BCB}
  {$DEFINE BCB7}{$DEFINE BCB}{$ELSE}{$DEFINE DELPHI2006}{$DEFINE DELPHI}
 {$ENDIF}
{$ENDIF}
{$IFDEF DELPHI2006}
 {$DEFINE DELPHI2006_UP}{$DEFINE DELPHI7_UP}{$DEFINE DELPHI6_UP}{$DEFINE DELPHI5_UP}{$DEFINE DELPHI4_UP}{$DEFINE DELPHI3_UP}{$DEFINE DELPHI2_UP}{$DEFINE DELPHI1_UP}
{$ENDIF}
unit qstrparser;
//Author: K.K.Jacewicz
{
 USAGE:
  1. add qstrparser to your uses list
  2. Create an object of Class TQSTR. you can call the constructor with GET and
     POST parameters, and then skip the next step to load these values if you
     have previously used your own code to retrieve them, or you can call a simple
     Create constructor with no params, to retrieve them automatically.
  4. Access querystring parameters with a TQSTR class's property Params,
     to read paramater's value by its name.
}

interface
{$IFDEF DELPHI}uses SysUtils;{$ENDIF}
{$IFDEF FPC}uses dos;{$ENDIF}

Const
    QSTR_error = #27;

Type
    TQSTR_src = (qGET,qPOST);
    TQSTR_param
     = record
        name  : WideString;
        Value : WideString;
        Src   : TQSTR_src;
       end;

    TQSTR
     = Class
        protected
        private
        {Private Variables}
         FParams       : array of TQSTR_param;
        {Private Property readers/writers}
         Function getParam(name: WideString): WideString; overload;
         Function getParam(index: Cardinal): WideString; overload;
        {Private procedures & functions}
         Procedure LoadQS(QS: WideString; Src: TQSTR_src);
         Function LoadGET: WideString;
         Function LoadPOST: WideString;
         Procedure ParseQS(GET,POST: WideString);
        public
         Constructor Create; overload;
         Constructor Create(GET,POST: WideString); overload;
         Destructor Free;

         Function ParamCount: Cardinal;
         Property Params[name: widestring]: widestring read getParam; default;
         //Property Params[index: cardinal]: widestring read getParam; default;
         Function ParamExists(name: widestring): Boolean;
       End;


implementation

Function EnvVar(ID: string): WideString;
  begin
  {$IFDEF FPC}
   Result := GetEnv(ID) ;
  {$ELSE Delphi}
   Result:=GetEnvironmentVariable(ID);
  {$ENDIF}
  end;

Constructor TQSTR.Create;
  Begin
    inherited;
    SetLength(FParams,0);
    self.ParseQS(LoadGET,LoadPOST);
  End;

Constructor TQSTR.Create(GET: WideString; POST: WideString);
  begin
    inherited Create;
    SetLength(FParams,0);
   ParseQS(GET,POST);
  end;

Function TQSTR.LoadGET: WideString;
  begin
   Result:=EnvVar('QUERY_STRING');
  end;

Function TQSTR.LoadPOST: WideString;
  var c: char;
  begin
   Result:='';
   while not eof(input) do
    begin
     read(c);
     Result:=Result+c;
    end;
  end;

Function TQSTR.ParamCount: Cardinal;
  begin
   Result:=Length(FParams);
  end;

Procedure TQSTR.LoadQS(QS: WideString; Src: TQSTR_src);
  var nam,val: WideString; p,ln: integer;
  begin
   QS:=QS+';';
   p:=Pos(';',QS); if(p<=0)then exit;
   while p>0 do
    begin
     nam:=Copy(QS,1,p-1); Delete(QS,1,p);
     p:=Pos('=',nam);
     if(p>0)then
        begin
         val:=nam; Delete(val,1,p);
         nam:=Copy(nam,1,p-1);
         ln:=ParamCount;
         SetLength(FParams,ln+1);
         FParams[ln].name:=nam;
         FParams[ln].Value:=val;
         FParams[ln].Src:=Src;
        end;
     p:=Pos(';',QS);
    end;
  end;

Procedure TQSTR.ParseQS(GET: WideString; POST: WideString);
  begin
   SetLength(FParams,0);
   LoadQS(GET,qGET);
   LoadQS(POST,qPOST);
  end;

Function TQSTR.getParam(name: WideString): WideString;
  var ln,i: cardinal;
  begin
   Result:=QSTR_error;
   ln:=ParamCount; if(ln=0)then exit;
   For i:=0 to ln-1 do
       if(FParams[i].name=name)then
         begin
           Result:=FParams[i].Value; break;
         end;
  end;

Function TQSTR.getParam(index: Cardinal): WideString;
  var ln: integer;
  begin
   Result:=QSTR_error;
   ln:=ParamCount;
   if(index>=ln)then exit;
   Result:=FParams[index].name+'='+FParams[index].Value;
  end;

Function TQSTR.ParamExists(name: WideString): Boolean;
  begin
   Result:=(self.Params[name]<>QSTR_error);
  end;

Destructor TQSTR.Free;
  Begin
   SetLength(FParams,0);
  End;

Begin
End.
